package com.xhtt.modules.inspection.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhtt.common.exception.RRException;
import com.xhtt.common.exception.RRExceptionEnum;
import com.xhtt.common.utils.DateUtils;
import com.xhtt.common.utils.PageUtils;
import com.xhtt.common.utils.Query;
import com.xhtt.modules.inspection.dao.InsLineMapper;
import com.xhtt.modules.inspection.dto.InsPointDTO;
import com.xhtt.modules.inspection.dto.InsTrackDTO;
import com.xhtt.modules.inspection.entity.*;
import com.xhtt.modules.inspection.enums.InspectStepStatusEnum;
import com.xhtt.modules.inspection.enums.ReleaseStatusEnum;
import com.xhtt.modules.inspection.enums.TaskStatusEnum;
import com.xhtt.modules.inspection.service.*;
import com.xhtt.modules.inspection.vo.InsLineVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 巡检线路 服务实现类
 * </p>
 *
 * @author xj
 * @since 2019-01-18
 */
@Service
public class InsLineServiceImpl extends ServiceImpl<InsLineMapper, InsLine> implements IInsLineService {

    @Autowired
    private IInsLinePointService insLinePointService;

    @Autowired
    private IInsLineService insLineService;

    @Autowired
    private IInsPointLabelService insPointLabelService;

    @Autowired
    private IInsTaskStepService insTaskStepService;

    @Autowired
    private IInsPointSubitemService insPointSubitemService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {

        Page<InsLine> page = new Query<InsLine>(params).getPage();
        page.setRecords(baseMapper.queryPage(page, params));
//        // 已经发布的线路
//        List<Integer> isReleaseIdList = new ArrayList<>();
//        // 发布
//        Integer releaseStatus = 0;
//        if (Optional.ofNullable(params.get("isRelease")).isPresent()) {
//            // 模糊查询已发布的任务数据集合
//            List<InsTask> insTasks = insTaskService
//                    .list(new LambdaQueryWrapper<InsTask>()
//                            .ge(InsTask::getTaskEndDate, DateUtils.now())
//                            .ne(InsTask::getTaskStatus, TaskStatusEnum.FINISH.getCode()));
//
//            isReleaseIdList = insTasks.stream().map(InsTask::getLineId).collect(Collectors.toList());
//
//            releaseStatus = Integer.parseInt(params.get("isRelease").toString());
//        }
//
//        Page<InsLine> page = new Query<InsLine>(params).getPage();
//
//        IPage<InsLine> iPage = baseMapper.selectPage(page, new LambdaQueryWrapper<InsLine>()
//                .like(Optional.ofNullable(params.get("name")).isPresent(), InsLine::getName, params.get("name"))
//                .eq(Optional.ofNullable(params.get("type")).isPresent(), InsLine::getType, params.get("type"))
//                .in(releaseStatus.equals(ReleaseStatusEnum.RELEASED.getCode()), InsLine::getId, isReleaseIdList)
//                .notIn(releaseStatus.equals(ReleaseStatusEnum.WAIT.getCode()), InsLine::getId, isReleaseIdList)
//                .orderByDesc(InsLine::getUpdateTime));
//
//
//        List<InsLine> insLineList = iPage.getRecords();
//        for (InsLine insLine : insLineList) {
//
//            // 设置是否显示预览轨迹按钮
//            Integer lineId = insLine.getId();
//            InsTrackDTO insTrackDTO = getInsTrackByLineId(lineId);
//            List<InsPointDTO> pointList = insTrackDTO.getPointList();
//            List<InsPointDTO> r = pointList.stream().filter(insPointDTO -> StringUtils.isEmpty(insPointDTO.getPosX()) || StringUtils.isEmpty(insPointDTO.getPosY())).collect(Collectors.toList());
//            insLine.setShowTrack(CollectionUtils.isEmpty(r));
//
//            // 默认全部设置为未发布
//            insLine.setIsRelease(ReleaseStatusEnum.WAIT.getCode());
//            // 如果发布列表中存在则设置为已发布
//            if (CollectionUtils.isNotEmpty(isReleaseIdList)) {
//                for (Integer isReleaseId : isReleaseIdList) {
//                    if (insLine.getId().equals(isReleaseId)) {
//                        insLine.setIsRelease(ReleaseStatusEnum.RELEASED.getCode());
//                    }
//                }
//            }
//        }
        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void add(InsLineVO insLineVO) {

        // 保存线路表
        InsLine insLine = new InsLine();

        // 线路名称唯一性
        int nameExist = baseMapper
                .selectCount(new LambdaQueryWrapper<InsLine>()
                        .eq(InsLine::getName, insLineVO.getName()));

        if (nameExist > 0) {
            throw new RRException(RRExceptionEnum.LINE_NAME_EXIST);
        }

        BeanUtils.copyProperties(insLineVO, insLine);
        baseMapper.insert(insLine);

        // 获取检测点集合
        List<InsPoint> insPointList = insLineVO.getInsPointList();

        // 创建检测点与线路关联
        InsLinePoint insLinePoint = new InsLinePoint();
        // 关联表设置线路id
        insLinePoint.setLineId(insLine.getId());
        for (InsPoint insPoint : insPointList) {
            // 关联表设置检测点id
            insLinePoint.setPointId(insPoint.getId());
            // 获取排序
            Integer sort = insLinePointService.getMaxSort(insLine.getId());
            if (sort == null) {
                sort = 0;
            }
            // 关联表设置排序
            insLinePoint.setSort(sort + 1);
            insLinePointService.save(insLinePoint);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(InsLineVO insLineVO) {

        // 保存线路表
        InsLine insLine = new InsLine();

        BeanUtils.copyProperties(insLineVO, insLine);

        // 线路名称唯一性
        int nameExist = baseMapper
                .selectCount(new LambdaQueryWrapper<InsLine>()
                        .eq(InsLine::getName, insLineVO.getName())
                        .ne(InsLine::getId, insLineVO.getId()));

        if (nameExist > 0) {
            throw new RRException(RRExceptionEnum.LINE_NAME_EXIST);
        }
        baseMapper.updateById(insLine);

        Integer lineId = insLine.getId();

        // 先全删
        insLinePointService.remove(new LambdaQueryWrapper<InsLinePoint>().eq(InsLinePoint::getLineId, lineId));

        // 获取检测点集合
        List<InsPoint> insPointList = insLineVO.getInsPointList();

        // 创建检测点与线路关联
        InsLinePoint insLinePoint = new InsLinePoint();

        // 关联表设置线路id
        insLinePoint.setLineId(lineId);

        for (InsPoint insPoint : insPointList) {
            // 获取排序
            Integer sort = insLinePointService.getMaxSort(insLine.getId());

            // 关联表设置检测点id
            insLinePoint.setPointId(insPoint.getId());


            if (null == sort) {
                sort = 0;
            }

            // 关联表设置排序
            insLinePoint.setSort(sort + 1);

            insLinePointService.save(insLinePoint);
        }

    }

    @Override
    public InsLineVO detail(Integer lineId) {

        InsLineVO insLineVO = new InsLineVO();

        // 主表
        InsLine insLine = insLineService.getById(lineId);

        BeanUtils.copyProperties(insLine, insLineVO);

        // 检点集合
        List<InsPoint> insPointList = insLinePointService.getInsPointListByLineId(lineId);

        // 添加标签信息
        insPointList.forEach(e -> {

            InsLabel insLabel = insPointLabelService.getInsLabelByPointId(e.getId());
            e.setLabelCode(insLabel.getCode());
            // 添加巡检内容
            e.setCheckList(insPointSubitemService.getInsPointSubByPointId(e.getId()));
            e.setLabelName(insLabel.getName());

        });

        insLineVO.setInsPointList(insPointList);

        return insLineVO;
    }

    @Override
    public InsLineVO detail(Integer lineId, Integer stepId) {

        InsLineVO insLineVO = new InsLineVO();

        // 主表
        InsLine insLine = insLineService.getAllById(lineId);

        BeanUtils.copyProperties(insLine, insLineVO);

        // 检点集合
        List<InsPoint> insPointList = insLinePointService.getInsPointListByLineId(lineId);

        // 无检点
        if (CollectionUtils.isEmpty(insPointList)) {
            throw new RRException(RRExceptionEnum.NO_POINT);
        }

        // 添加标签信息
        insPointList.forEach(e -> {

            List<Integer> insTaskSteps = new ArrayList<>(insTaskStepService.getTaskStepPointChecked(stepId));

            insTaskSteps.forEach(m -> {
                if (e.getId().equals(m)) {
                    e.setStatus(InspectStepStatusEnum.FINISH.getCode());
                }
            });

            InsLabel insLabel = insPointLabelService.getInsLabelByPointId(e.getId());
            e.setLabelCode(insLabel.getCode());
            // 添加巡检内容
            e.setCheckList(insPointSubitemService.getInsPointSubByPointId(e.getId()));
            e.setLabelName(insLabel.getName());

        });

        insLineVO.setInsPointList(insPointList);

        return insLineVO;
    }


    @Override
    public InsTrackDTO getInsTrackByLineId(Integer lineId) {

        InsTrackDTO insTrackDTO = new InsTrackDTO();

        insTrackDTO.setLineId(lineId);

        List<InsPoint> insPointList = insLinePointService.getInsPointListByLineId(lineId);

        // 获取线路对应的所有的检测点id
        List<InsLinePoint> insLinePointList = insLinePointService
                .list(new LambdaQueryWrapper<InsLinePoint>()
                        .eq(InsLinePoint::getLineId, lineId));

        List<InsPointDTO> insPointDTOList = new ArrayList<>();

        // 创建InsPointDTO对象
        for (InsPoint insPoint : insPointList) {
            for (InsLinePoint insLinePoint : insLinePointList) {
                if (insPoint.getId().equals(insLinePoint.getPointId())) {

                    // 最外层对象设置线路名称
                    insTrackDTO.setName(insLineService.getById(lineId).getName());

                    InsPointDTO insPointDTO = new InsPointDTO();

                    // 将linePoint表里面排序字段赋值给insPointDTO
                    insPointDTO.setSort(insLinePoint.getSort());
                    insPointDTO.setPointId(insPoint.getId());
                    insPointDTO.setPointName(insPoint.getName());
                    insPointDTO.setDeviceName(insPoint.getDeviceName());
                    insPointDTOList.add(insPointDTO);
                }
            }
        }

        // 添加坐标属性
        for (InsPointDTO insPointDTO : insPointDTOList) {
            InsLabel insLabel = insPointLabelService.getInsLabelByPointId(insPointDTO.getPointId());
            insPointDTO.setPosX(insLabel.getPosX());
            insPointDTO.setPosY(insLabel.getPosY());
        }
        // 排序
        insPointDTOList.sort(Comparator.comparing(InsPointDTO::getSort));
        insTrackDTO.setPointList(insPointDTOList);

        return insTrackDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Integer> lineId) {

        // 删除主表
        baseMapper.deleteBatchIds(lineId);

        // 删除关联表
        // 逻辑删除不取消关联
//        insLinePointService.remove(new LambdaQueryWrapper<InsLinePoint>().in(InsLinePoint::getLineId, lineId));
    }

    @Override
    public List<InsLine> getListByName(String lineName) {

        return baseMapper.selectList(new LambdaQueryWrapper<InsLine>().like(InsLine::getName, lineName));
    }

    @Override
    public InsLine getAllById(Integer lineId) {
        return baseMapper.queryById(lineId);
    }
}
